package com.woniuxy.secondkill.controller;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
public class KillController {
    @Resource
    private RedisTemplate<String ,Object> redisTemplate;

    //@GetMapping("/kill")
    public boolean kill(){
        synchronized (KillController.class){
            //1读取库存
            Integer nums = (Integer) redisTemplate.opsForValue().get("nums");
            //2判断库存，进行秒杀
            if(nums>0){
                nums--;
                System.out.println("nums还剩："+nums);
                redisTemplate.opsForValue().set("nums",nums);
                return true;
            }
        }
        return false;
    }
    /*
    * 使用setnx实现分布式锁
    * */
    //@GetMapping("/kill")
    public boolean kill2(){
        boolean flag = false;
        String key = "lock";
        String uuid = UUID.randomUUID().toString();
        //setIfAbsent底层调用setnx指令,设置过期时间
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, uuid,10, TimeUnit.SECONDS);
        //设置过期时间
        //redisTemplate.expire(key,10, TimeUnit.SECONDS);

        if(!result){
            return flag;
        }
        try{
            //获得锁
            //1读取库存
            Integer nums = (Integer) redisTemplate.opsForValue().get("nums");
            //2判断库存，进行秒杀
            if(nums>0){
                nums--;
                System.out.println("nums还剩："+nums);
                redisTemplate.opsForValue().set("nums",nums);
                flag = true;
            }
        }finally {
            //释放锁,删除锁key 可能会删除其他线程的key，
            if(uuid.equals(redisTemplate.opsForValue().get(key))){
                redisTemplate.delete(key);
            }
        }
        return flag;
    }
    /*
    *
    * 3使用redisson分布式锁
    * */
    @Resource
    private Redisson redisson;

    @GetMapping("/kill")
    public boolean kill3(){
        boolean flag = false;
        String key = "lock";
        //获取锁 setnx 默认过期时间10s  续命时间也是10s
        RLock lock = redisson.getLock(key);
        try{
            //锁定自身线程
            lock.lock();
            //1读取库存
            Integer nums = (Integer) redisTemplate.opsForValue().get("nums");
            //2判断库存，进行秒杀
            if(nums>0){
                nums--;
                System.out.println("nums还剩："+nums);
                redisTemplate.opsForValue().set("nums",nums);
                flag = true;
            }
        }finally {
            //释放锁
            lock.unlock();
        }
        return flag;
    }
}
